<!--
 * Copyright 2022 The kubegems.io Authors
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
-->

<template>
  <BaseFullScreenDialog
    v-model="dialog"
    icon="mdi-history"
    :logo="config.layout.LOGO_WHITE"
    :title="$t('tip.query_history')"
    @dispose="handleDispose"
  >
    <template #action>
      <div class="mt-1 float-right">
        <ProjectEnvSelectCascade
          :key="selectKey"
          v-model="environment"
          first
          reverse
          reverse-color
          :small="false"
          :tenant="tenant"
        />
      </div>
    </template>
    <template #content>
      <v-card v-if="dialog" class="log-history" flat>
        <v-data-table
          class="px-4"
          :headers="headers"
          hide-default-footer
          item-key="ID"
          :items="items"
          :items-per-page="-1"
          :no-data-text="$root.$t('data.no_data')"
          show-expand
          single-expand
          :sort-by="['CreateAt']"
          :sort-desc="[true]"
        >
          <template #[`item.label`]="{ item }">
            <span v-for="(v, k) in item.LabelJSON" :key="k">
              <v-chip
                v-for="(labelValue, labelIndex) in v"
                :key="labelIndex"
                class="ma-1 font-weight-medium"
                color="success"
                small
              >
                <span class="pr-2">{{ $t('tip.label') }}({{ k }}):{{ labelValue }}</span>
              </v-chip>
            </span>
            <v-chip
              v-for="(it, index) in item.FilterJSON"
              :key="it + index"
              class="ma-1 font-weight-medium"
              color="success"
              small
            >
              <span class="pr-2">{{ $t('tip.regex') }}(regex):{{ it }}</span>
            </v-chip>
          </template>
          <template #[`item.createAt`]="{ item }">
            {{ item.CreateAt ? $moment(item.CreateAt).format('lll') : '' }}
          </template>
          <template #[`item.logQL`]="{ item }">{{ item.LogQL }}</template>
          <template #[`item.total`]="{ item }">{{ item.Total }}</template>
          <template #[`item.action`]="{ item }">
            <v-flex class="float-right">
              <v-btn class="my-1" color="primary" small text @click="handleQuery(item)">
                {{ $t('operate.query') }}
              </v-btn>
              <v-btn class="my-1" color="error" small text @click="handleDelete(item)">
                {{ $root.$t('operate.delete') }}
              </v-btn>
            </v-flex>
            <div class="kubegems__clear-float" />
          </template>
          <template #expanded-item="{ headers, item }">
            <td class="my-2 py-2" :colspan="headers.length">
              <div
                v-for="(time, index) in getQueryDatetimes(item.TimeRanges)"
                :key="index"
                class="text-caption mx-1 float-left"
              >
                <div class="float-left">
                  {{ time.s }} - {{ time.e }}
                  <v-btn class="mt-n1" color="primary" small text @click="handleQuery(item, time)">
                    {{ $t('operate.timerange_query') }}
                  </v-btn>
                </div>
                <div class="float-left log-histroy__split" />
              </div>
            </td>
          </template>
        </v-data-table>
      </v-card>
    </template>
  </BaseFullScreenDialog>
</template>

<script>
  import { deleteLogQueryHistory, getLogQueryHistoryList } from '@kubegems/api/direct';
  import config from '@kubegems/libs/constants/global';
  import { randomString } from '@kubegems/libs/utils/helpers';
  import BaseSelect from '@kubegems/mixins/select';
  import { mapGetters } from 'vuex';

  import ProjectEnvSelectCascade from '../../../components/ProjectEnvSelectCascade';
  import messages from '../../i18n';

  export default {
    name: 'LogHistory',
    i18n: {
      messages: messages,
    },
    components: {
      ProjectEnvSelectCascade,
    },
    mixins: [BaseSelect],
    inject: ['reload'],
    data() {
      this.config = config;

      return {
        dialog: false,
        clusterid: undefined,
        items: [],
        namespace: '',
        tenant: null,
        environment: undefined,
        selectKey: '',
      };
    },
    computed: {
      ...mapGetters(['Tenant']),
      env() {
        const env = this.m_select_environmentItems.find((e) => {
          return e.value === this.namespace;
        });
        return env;
      },
      headers() {
        return [
          { text: 'LogQL', value: 'logQL', align: 'start', sortable: false },
          { text: this.$t('tip.label'), value: 'label', align: 'start', sortable: false },
          { text: this.$t('table.last_query_at'), value: 'createAt', align: 'start', width: 200 },
          { text: this.$t('table.count'), value: 'total', align: 'start', width: 100 },
          { text: '', value: 'action', align: 'end', width: 140, sortable: false },
          { text: '', value: 'data-table-expand' },
        ];
      },
    },
    watch: {
      environment: {
        handler(newValue) {
          if (newValue) {
            this.clusterid = newValue.clusterid;
            this.getHistoryList();
          }
        },
        deep: true,
        immediate: true,
      },
    },
    methods: {
      show() {
        this.dialog = true;
        this.m_select_environmentSelectData();
        this.tenant = this.Tenant();
        this.selectKey = `history-${randomString(4)}`;
      },

      async getHistoryList() {
        const data = await getLogQueryHistoryList(this.clusterid);
        this.items = (data || []).map((item) => {
          return {
            ...item,
            LabelJSON: this.handleParseLabel(item.LogQL),
            FilterJSON: this.handleParseFilter(item.LogQL),
          };
        });
      },
      handleParseLabel(input) {
        const labelMatchArr = input.match(new RegExp('{(.*)}'));
        if (labelMatchArr && labelMatchArr.length > 1) {
          const labelArr = labelMatchArr[1].split(',');
          const labelValueObj = {};
          labelArr.forEach((item) => {
            if (item.indexOf('=~') !== -1) {
              const label = item.split('=~')[0];
              labelValueObj[label] = item.split('=~')[1].match(new RegExp('"(.*)"'))[1].split('|');
            } else {
              const label = item.split('=')[0];
              labelValueObj[label] = [item.split('=')[1].match(new RegExp('"(.*)"'))[1]];
            }
          });
          return labelValueObj;
        } else {
          return {};
        }
      },

      handleParseFilter(input) {
        const filterList = [];
        const matchedArr = input.match(new RegExp('{.*}(.*)'));
        if (matchedArr && matchedArr.length > 1) {
          const filterArr = matchedArr[1].trim().split('|~');
          filterArr.forEach((item) => {
            if (item !== '') {
              const match = item.match(new RegExp('`(.*)`'));
              if (match && match.length > 0) {
                filterList.push(match[1]);
              }
            }
          });
        }
        return filterList;
      },

      async handleQuery(item, timeRange = {}) {
        this.dialog = false;
        const ns = new RegExp('namespace="([\\w-#\\(\\)\\*\\.@\\?&^$!%<>\\/]+)"', 'g').exec(item.LogQL);
        if (ns) {
          this.namespace = ns[1];
        }
        const env = this.env;

        if (this.namespace && env) {
          await this.$router.replace({
            query: {
              query: item.LogQL,
              project: env.projectName,
              environment: env.text,
              cluster: env.clusterName,
              namespace: this.namespace,
              filters: item.FilterJSON,
              start: timeRange.start || null,
              end: timeRange.end || null,
            },
          });
          this.reload();
        } else {
          this.$store.commit('SET_SNACKBAR', {
            text: this.$t('tip.parse_namespace_error'),
            color: 'warning',
          });
        }
      },

      async handleDelete(item) {
        this.$store.commit('SET_CONFIRM', {
          title: this.$root.$t('operate.delete_c', [this.$t('tip.query_history')]),
          content: {
            text: item.LogQL,
            type: 'confirm',
          },
          doFunc: async () => {
            const ids = item.Ids.split(',')
              .reduce((pre, current) => pre + `lid=${current}&`, '')
              .slice(0, -1);
            await deleteLogQueryHistory(ids);
            this.getHistoryList();
          },
        });
      },

      handleDispose() {
        this.cluster = undefined;
        this.items = [];
      },
      getQueryDatetimes(timeRanges) {
        const times = timeRanges.split(',').filter((time) => {
          return Boolean(time);
        });
        return times.map((t) => {
          const timeR = t.split('|');
          if (timeR?.length > 1) {
            const startTimestamp = timeR[0];
            const endTimestamp = timeR[1];
            return {
              start: startTimestamp,
              end: endTimestamp,
              s: this.$moment(new Date(parseInt(startTimestamp))).format('lll'),
              e: this.$moment(new Date(parseInt(endTimestamp))).format('lll'),
            };
          }
        });
      },
    },
  };
</script>

<style lang="scss" scoped>
  .log-histroy {
    position: absolute;
    top: 64px;
    right: 0;
    bottom: 0;
    left: 0;
    overflow: auto;

    &::-webkit-scrollbar {
      display: block !important;
    }
    &::-webkit-scrollbar-thumb {
      width: 10px;
      border-radius: 5px;
      background: grey;
      box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
    }
    &::-webkit-scrollbar:vertical {
      width: 10px;
    }

    &__split {
      border-right: 1px solid grey;
      width: 1px;
      height: 22px;
    }
  }
</style>
